#ifndef UTILS_HEADER
#define UTILS_HEADER

#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<map>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include "def.hpp"
#include "singleton.hpp"
#include "lngamma.hpp"
#include "digamma.hpp"

using namespace std;

namespace Puza{
  template <class T> bool from_string(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&)){
    std::istringstream iss(s);
    return !(iss >> f >> t).fail();
  }
  
  template <class T>
  std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
  {
    std::ostringstream oss;
    oss << f << t;
    return oss.str();
  }

  template<class T>
  void allocate_memory(T**& container,const int &m, const int &n){
    container = new T*[m];
    for(int i=0;i<m;i++){
      container[i] = new T[n];
      for (int j=0;j< n;j++)
	container[i][j] = (T)0.0;
    }
  }

  template<class T>
  void dellocate_memory(T**& container,const int &m, const int &n){
    for(int i=0;i<m;i++){
      delete[] container[i];
    }
    delete[] container;
  }
  class Utils{
  public:
    virtual double get_sum(double*& buffer, int& K);
    virtual double log_sum(double log_a, double log_b);
    virtual double log_sub(double log_a, double log_b);
    virtual double log_sum_array(double*& buffer, int K);
    virtual double log_sum_vector(vector<double>& buffer);
    virtual double digamma(double x);
    virtual double log_gamma(double x);
    virtual double sum_log_gamma(double*& buffer, int& K); // \sum \log \Gamma(x)
    virtual double l1_distance(double*& a, double*& b, int& K);
    virtual double l2_distance(double*& a, double*& b, int& K);
    virtual double Trunc(double,double); // truncation function for L1 regularization                                                                                                                                                                  
    virtual double Min(double,double);
    virtual double Max(double,double);
    virtual int uniform_int_sample(int,int);
    virtual double uniform_double_sample(double,double);
  };

  typedef Singleton<Utils> PuzaUtils;
};
#endif
  
